/*
 * parsingUtilTest.c
 *
 * This is the test file the exercise some unit tests on the main code cleaning logic
 * used in this project.
 *
 * Created on: Oct 25, 2011
 * Author: shaohong
 */


#include "parsingUtils.h"

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

void testIsEmptyLine()
{
	fprintf(stderr, "Running Unit Test ==> \"%s\"\n", __func__);

	char * line = "";
	assert(isEmptyLine(line));

	line = "   ";
	assert(isEmptyLine(line));

	line = "   \n";
	assert(isEmptyLine(line));

	line = " \t  \n";
	assert(isEmptyLine(line));

	//This is not an empty line!
	line = "  asdf ";
	assert(! isEmptyLine(line));

}
void testEmptyLine()
{
	fprintf(stderr, "Running Unit Test ==> \"%s\"\n", __func__);
	LineParsingContext initialContext;
	initialContext.codeLine = "    \n"; /*here we have an empty line*/
	initialContext.parserState = NORMAL_LINE;

	LineParsingContext * resultContext;
	resultContext = getCodePartFromLine(&initialContext);

	/*check and make sure the result is not NULL*/
	assert (NULL != resultContext);

	/* the parserState after parsing should still be NORMAL_LINE*/
	assert(NORMAL_LINE == resultContext->parserState);

	/* "Valuable code" should be empty in this case.*/
	assert(NULL == resultContext->codeLine);
}

/**
 * Unit tests testing the scenario of " code ".
 * In this case code cleaner won't throw away anthing
 */
void testSingleLineNoComments()
{
	fprintf(stderr, "Running Unit Test ==> \"%s\"\n", __func__);
	LineParsingContext initialContext;
	initialContext.codeLine = "   CODE   ";
	initialContext.parserState = NORMAL_LINE;

	LineParsingContext * resultContext;
	resultContext = getCodePartFromLine(&initialContext);

	/*check and make sure the result is not NULL*/
	assert (NULL != resultContext);

	/* the parserState after parsing should still be NORMAL_LINE*/
	assert(NORMAL_LINE == resultContext->parserState);

	/* "Valuable code" should not be empty in this case.*/
	assert(NULL != resultContext->codeLine);

	/* "Valuable code" should be "CODE   " in this case.*/
	assert(0 == strcmp(initialContext.codeLine, resultContext->codeLine));
}


/**
 * unit tests that testing the parsing of "  //COMMENTS "; (no valuable part)
 */
void testSingleLine1()
{

	fprintf(stderr, "Running Unit Test ==> \"%s\"\n", __func__);
	LineParsingContext initialContext;
	initialContext.codeLine = "   //comments   \n";
	initialContext.parserState = NORMAL_LINE;

	LineParsingContext * resultContext;
	resultContext = getCodePartFromLine(&initialContext);

	/*check and make sure the result is not NULL*/
	assert (NULL != resultContext);

	/* the parserState after parsing should still be NORMAL_LINE*/
	assert(NORMAL_LINE == resultContext->parserState);

	/* "Valuable code" should be empty in this case.*/
	assert(NULL == resultContext->codeLine);
}


/**
 * unit tests that testing the parsing of "CODE  //COMMENTS "; (no valuable part)
 */
void testSingleLine2()
{
	fprintf(stderr, "Running Unit Test ==> \"%s\"\n", __func__);
	LineParsingContext initialContext;
	initialContext.codeLine = "CODE   //comments   \n";
	initialContext.parserState = NORMAL_LINE;

	LineParsingContext * resultContext;
	resultContext = getCodePartFromLine(&initialContext);

	/*check and make sure the result is not NULL*/
	assert (NULL != resultContext);

	/* the parserState after parsing should still be NORMAL_LINE*/
	assert(NORMAL_LINE == resultContext->parserState);

	/* "Valuable code" should not be empty in this case.*/
	assert(NULL != resultContext->codeLine);

	/* "Valuable code" should be "CODE   " in this case.*/
	assert(0 == strcmp("CODE   \n", resultContext->codeLine));
}

// test single line scenarios:
// /*COMMENTS*/ CODE; ("CODE" is the valuable part)
void testSingleLine3()
{
	fprintf(stderr, "Running Unit Test ==> \"%s\"\n", __func__);
	LineParsingContext initialContext;
	initialContext.codeLine = " CODE1 /*COMMENTS*/ CODE2 ";
	initialContext.parserState = NORMAL_LINE;

	LineParsingContext * resultContext;
	resultContext = getCodePartFromLine(&initialContext);

	/*check and make sure the result is not NULL*/
	assert (NULL != resultContext);

	/* the parserState after parsing should still be NORMAL_LINE*/
	assert(NORMAL_LINE == resultContext->parserState);

	/* "Valuable code" should not be empty in this case.*/
	assert(NULL != resultContext->codeLine);

	/* "Valuable code" should be " CODE1  CODE2 " in this case.*/
	assert(0 == strcmp(" CODE1  CODE2 ", resultContext->codeLine));
}


// test single line scenarios:
// "  /*COMMENTS*/ "; so there is no valuable part in this line
//
void testSingleLine4()
{
	fprintf(stderr, "Running Unit Test ==> \"%s\"\n", __func__);
	LineParsingContext initialContext;
	initialContext.codeLine = " /*COMMENTS*/ ";
	initialContext.parserState = NORMAL_LINE;

	LineParsingContext * resultContext;
	resultContext = getCodePartFromLine(&initialContext);

	/*check and make sure the result is not NULL*/
	assert (NULL != resultContext);

	/* the parserState after parsing should still be NORMAL_LINE*/
	assert(NORMAL_LINE == resultContext->parserState);

	/* "Valuable code" should be empty in this case.*/
	assert(NULL == resultContext->codeLine);
}

// test single line scenarios:
// "CODE1 /*COMMENTS1*/ CODE2 //COMMENTS2"
// So "CODE1  CODE2 " are valuable code
//
void testSingleLine5()
{
	fprintf(stderr, "Running Unit Test ==> \"%s\"\n", __func__);
	LineParsingContext initialContext;
	initialContext.codeLine = "CODE1 /*COMMENTS1*/ CODE2 //COMMENTS2";
	initialContext.parserState = NORMAL_LINE;

	LineParsingContext * resultContext;
	resultContext = getCodePartFromLine(&initialContext);

	/*check and make sure the result is not NULL*/
	assert (NULL != resultContext);

	/* the parserState after parsing should still be NORMAL_LINE*/
	assert(NORMAL_LINE == resultContext->parserState);

	/* "Valuable code" should not be empty in this case.*/
	assert(NULL != resultContext->codeLine);

	/* "Valuable code" should be "CODE1  CODE2 " in this case.*/
	assert(0 == strcmp("CODE1  CODE2 ", resultContext->codeLine));
}

// Test multiple line comments scenario: /*COMMENTS_spans_several_lines*/
// in this case, the first line is something like "   /* comments "
// therefore we expect the code line to be NULL/empty and the parserState is BLOCKING_COMMENT
void testMultipleLine_firstLine()
{
	fprintf(stderr, "Running Unit Test ==> \"%s\"\n", __func__);
	LineParsingContext initialContext;
	initialContext.codeLine = " /*COMMENTS1 \n ";
	initialContext.parserState = NORMAL_LINE;

	LineParsingContext * resultContext;
	resultContext = getCodePartFromLine(&initialContext);

	/*check and make sure the result is not NULL*/
	assert(NULL != resultContext);

	/* the parserState after parsing should be IN_BLOCK_COMMENTING*/
	assert(IN_BLOCK_COMMENTING == resultContext->parserState);

	/* "Valuable code" should be empty in this case.*/
	assert((NULL == resultContext->codeLine)
			|| (strlen(resultContext->codeLine)==0));

}

// Test multiple line comments scenario: /*COMMENTS_spans_several_lines*/
// in this case, the first line is something like "   /* comments "
// therefore we expect the code line to be NULL/empty and the parserState is BLOCKING_COMMENT
void testMultipleLine_firstLine_2()
{
	fprintf(stderr, "Running Unit Test ==> \"%s\"\n", __func__);
	LineParsingContext initialContext;
	initialContext.codeLine = "  SomeCode /*COMMENTS1 \n ";
	initialContext.parserState = NORMAL_LINE;

	LineParsingContext * resultContext;
	resultContext = getCodePartFromLine(&initialContext);

	/*check and make sure the result is not NULL*/
	assert(NULL != resultContext);

	/* the parserState after parsing should be IN_BLOCK_COMMENTING*/
	assert(IN_BLOCK_COMMENTING == resultContext->parserState);

	/* "Valuable code" is "  SomeCode " in this case.*/
	char * expectedStr = "  SomeCode ";
	assert(0 == strcmp(expectedStr, resultContext->codeLine));

}

// Test multiple line comments scenario: /*COMMENTS_spans_several_lines*/
// in this case,anything in the intermediate lines are not valuable code
// therefore we expect the code line to be NULL/empty and the parserState is BLOCKING_COMMENT
// "intermediate line" means the line that doesn't contain "*/"
void testMultipleLine_intermediateLine()
{
	fprintf(stderr, "Running Unit Test ==> \"%s\"\n", __func__);
	LineParsingContext initialContext;

	initialContext.codeLine = " ANYTHING ";

	initialContext.parserState = IN_BLOCK_COMMENTING;

	LineParsingContext * resultContext;
	resultContext = getCodePartFromLine(&initialContext);

	/*check and make sure the result is not NULL*/
	assert(NULL != resultContext);

	/* the parserState after parsing should be IN_BLOCK_COMMENTING*/
	assert(IN_BLOCK_COMMENTING == resultContext->parserState);

	/* "Valuable code" should be empty in this case.*/
	assert((NULL == resultContext->codeLine)
			|| (strlen(resultContext->codeLine)==0));

}


// Test multiple line comments scenario: /*COMMENTS_spans_several_lines*/
// in this case,anything in on the last line after "*/" are valuable
// "last line" means the line that contains "*/"
void testMultipleLine_LastLine()
{
	fprintf(stderr, "Running Unit Test ==> \"%s\"\n", __func__);
	LineParsingContext initialContext;

	initialContext.codeLine = " COMMENTS */ CODE";

	initialContext.parserState = IN_BLOCK_COMMENTING;

	LineParsingContext * resultContext;
	resultContext = getCodePartFromLine(&initialContext);

	/*check and make sure the result is not NULL*/
	assert(NULL != resultContext);

	/* the parserState after parsing should be NORMAL_LINE*/
	assert(NORMAL_LINE == resultContext->parserState);

	/* "Valuable code" is "  SomeCode " in this case.*/
	char * expectedStr = " CODE";
	assert(0 == strcmp(expectedStr, resultContext->codeLine));

}


int main(int argc, char ** argv)
{
	testSingleLineNoComments();

	testIsEmptyLine();

	testEmptyLine();

	testSingleLine1();

	testSingleLine2();

	testSingleLine3();

	testSingleLine4();

	testSingleLine5();

	testMultipleLine_firstLine();

	testMultipleLine_firstLine_2();

	testMultipleLine_intermediateLine();

	testMultipleLine_LastLine();


	fprintf(stderr, "=====================\n");
	fprintf(stderr, "WOW! All test passed!\n");
	fprintf(stderr, "=====================\n");

	return EXIT_SUCCESS;
}
